package com.esig.Model;

import com.esig.View.GameFrame;
import com.esig.util.BulletsPool;
import com.esig.util.Direction;
import com.esig.util.State;

import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Map;

/**
 * 主角之一  Davis
 */
public class PlayerOther extends Role implements Runnable {

    public int id; //唯一id
    public int hp = 80; //当前生命值 默认是80


    private boolean up = false;
    private boolean left = false;
    private boolean right = false;
    private boolean down = false;

    private BloodBar bar = new BloodBar(); //实例化子弹内部类

    //构造方法
    public PlayerOther(String img, GameFrame gameFrame, Integer id, String leftImg_0, String leftImg_1, String leftImg_2, String rightImg_0, String rightImg_1, String rightImg_2) {
        super(img, gameFrame, leftImg_0, leftImg_1, leftImg_2, rightImg_0, rightImg_1, rightImg_2);
        this.id = id;
    }

    //构造方法 带精灵图截取
    public PlayerOther(String img, int dx1, int dy1, int dx2, int dy2, GameFrame gameFrame, String leftImg_0, String leftImg_1, String leftImg_2, String rightImg_0, String rightImg_1, String rightImg_2) {
        super(img, dx1, dy1, gameFrame, leftImg_0, leftImg_1, leftImg_2, rightImg_0, rightImg_1, rightImg_2);
        this.dx1 = dx1;
        this.dx2 = dx2;
        this.dy1 = dy1;
        this.dy2 = dy2;
    }


    @Override
    public void paintSelf(Graphics g) {
        /**
         * 绘制自身
         * 然后就是截取的范围（左上和右下两个点）精灵图一般一格是80*80
         *
         * 其中img是Image图片对象，而d开头的都是destinetiong，s开头的是source。
         * 也就是说在这里，你分别定义好来源和目标的两个矩形的左上角和右下角的点，它会自动帮你剪裁和适应。
         * 当然为了保证不失真，最好宽度和高度相同。
         */
        g.drawImage(Toolkit.getDefaultToolkit().getImage("src/main/resources/img/shadow.png"), dx1 + 22, dy2 - 10 + sDy, null); //绘制跳跃时的阴影  sDy 跳跃时阴影和人物的高度距离
        g.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null); //画出玩家
        g.drawString(String.valueOf(id), dx1 + 32, dy1 - 15);  //画出唯一ID
        move(); //移动方法
        hit(); //碰撞方法
        bar.draw(g); //绘制血条
    }

    public void paintSelfHelp(Graphics g) { //帮助界面
        g.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null); //画出玩家
        move(); //移动方法
    }

    /**
     * 设置矩形大小去实现物品碰撞等
     *
     * @return
     */
    @Override
    public Rectangle getRec() {
        //这里dx1和dy1是目标（图）上的左上角，宽度右右下角的x减左上角的x，y同理
        return new Rectangle(dx1 + 10, dy1, dx2 - dx1 - 20, dy2 - dy1); //设置了矩形但是图片大小没有改变
    }

    public Thread OtherThread;

    //碰撞方法
    public void hit() {
        Rectangle my = this.getRec();  //getRec() 是获取当前对象的矩形
        Map<Integer, PlayerOther> players = this.gameFrame.playerOtherList; //遍历玩家列表

        for (PlayerOther playerOther : players.values()) { //批量获取值  和其他人碰撞
            if (my.intersects(playerOther.getRec()) && this != playerOther) {  //intersects是判断矩形是否碰撞
//                System.out.println(this + "碰到了" + playerOther);
                if (attackOnly) {   //判断是不是那一帧
                    playerOther.hp -= this.attack;

                    if (state == State.ATTACK_ONE) {
                        playerOther.mStopTime = 0;
                        playerOther.keyCode = KeyEvent.VK_M; //设置线程标识为受伤
                        OtherThread = new Thread(playerOther);
                        OtherThread.start();
                        playerOther.injuredOne();

                    } else if (state == State.ATTACK_TWO) {
                        playerOther.mStopTime = 0;
                        playerOther.keyCode = KeyEvent.VK_M; //设置线程标识为受伤
                        if (OtherThread == null) {
                            OtherThread = new Thread(playerOther);
                            OtherThread.start();
                        }
                        new Thread(playerOther).start();
                        playerOther.injuredTwo();

                    } else if (state == State.ATTACK_THREE || state == State.SKILL_ONE_ONE) {
                        playerOther.mStopTime = 0;
                        playerOther.keyCode = KeyEvent.VK_M; //设置线程标识为受伤
                        if (OtherThread == null) {
                            OtherThread = new Thread(playerOther);
                            OtherThread.start();
                        }
                        playerOther.changeTimerParameter = "受伤浮空";
                        playerOther.changeOnStart();
                        playerOther.injuredThree();

                    } else if (state == State.ATTACK_JUMP || state == State.ATTACK_RUN) {
                        playerOther.mStopTime = 0;
                        playerOther.keyCode = KeyEvent.VK_M; //设置线程标识为受伤
                        if (OtherThread == null) {
                            OtherThread = new Thread(playerOther);
                            OtherThread.start();
                        }
                        playerOther.injuredThree();
                    }

                    attackOnly = false;  //判断是否处理攻击那一帧
                    System.out.println(playerOther + "受伤了");
                }
            }
            /********* 子弹碰撞 ***********/
            ArrayList<Bullet> bullets = this.gameFrame.bulletList; //遍历玩家列表

            for (Bullet bullet : bullets) { //批量获取值  和子弹碰撞
                if (playerOther.getRec().intersects(bullet.getRec()) && bullet.imgTimerParameter != "右子弹消失更改图片" && bullet.imgTimerParameter != "左子弹消失更改图片" && playerOther.state != State.INJUREDTHREE) {  //intersects是判断矩形是否碰撞
                    System.out.println(playerOther + "碰到了子弹");
                    System.out.println(!(my.intersects(bullet.getRec())));
                    playerOther.hp -= bullet.attack;
                    if (bullet.direction == Direction.RIGHT) {
                        bullet.imgTimerParameter = "右子弹消失更改图片";
                        bullet.imgOnStart();
                    } else {
                        bullet.imgTimerParameter = "左子弹消失更改图片";
                        bullet.imgOnStart();
                    }
                    if (playerOther.state == State.INJUREDONE) {
                        playerOther.mStopTime = 0;
                        playerOther.keyCode = KeyEvent.VK_M; //设置线程标识为受伤
                        OtherThread = new Thread(playerOther);
                        OtherThread.start();
                        playerOther.injuredTwo();

                    } else if (playerOther.state == State.INJUREDTWO) {
                        playerOther.mStopTime = 0;
                        playerOther.keyCode = KeyEvent.VK_M; //设置线程标识为受伤
                        OtherThread = new Thread(playerOther);
                        OtherThread.start();
                        playerOther.injuredThree();

//                    } else if(playerOther.state != State.INJUREDTHREE) {       //除了处于受伤一段和二段的其他,并且不倒地处理 这里判断加上，虽然不掉血，但是碰到子弹还是消失了
                    } else {
                        playerOther.mStopTime = 0;
                        playerOther.keyCode = KeyEvent.VK_M; //设置线程标识为受伤
                        OtherThread = new Thread(playerOther);
                        OtherThread.start();
                        playerOther.injuredOne();
                    }
                }
            }


        }

    }

    /**
     * 按下事件
     *
     * @param keyCode
     */
    public void keyPressed(int keyCode) {
        switch (keyCode) {
            //上下左右移动
            case KeyEvent.VK_A:
                keyPA();
                break;
            case KeyEvent.VK_S:
                down = true;
                break;
            case KeyEvent.VK_D:
                keyPD();
                break;
            case KeyEvent.VK_W:
                up = true;
                break;
            case KeyEvent.VK_J:
                keyJ();
                break;
            case KeyEvent.VK_K:
                jump();
                break;
            case KeyEvent.VK_L:
//                defense();   防御还没写
                break;
            case KeyEvent.VK_U:
                killOneOne();
                break;
            case KeyEvent.VK_I:
                keyI();
                break;
            default:
                break;
        }
    }

    /**
     * 松开事件
     *
     * @param keyCode
     */
    public void keyReleased(int keyCode) {
        switch (keyCode) {
            case KeyEvent.VK_A:
                keyRA();
                break;
            case KeyEvent.VK_S:
                down = false;
                moveStop();
                break;
            case KeyEvent.VK_D:
                keyRD();
                break;
            case KeyEvent.VK_W:
                up = false;
                moveStop();
                break;
            default:
                break;
        }
    }

    public void move() {
        if (left) {
            leftWalk();
        } else if (right) {
            rightWalk();
        } else if (up) {
            upWalk();
        } else if (down) {
            downWalk();
        }
    }

    //按键变量
    public int keyCode = 0;

    //按键j的方法
    public int jTimes = 1;  //攻击段数
    public long jStopTime = 0;   //收拳时间 判断x ms内，没有再次按下平a就收拳
    public long jPressTime = 0;  //按下时间

    public void keyJ() {
        keyCode = KeyEvent.VK_J;
        if (jTimes == 1) {
            jStopTime = 0;
            if (state == State.STAND || state == State.WALK) {
                new Thread(this).start();
                jPressTime = System.currentTimeMillis();
                attackOne();
                jTimes++;
            } else if (state == State.ATTACK_THREE && System.currentTimeMillis() - jPressTime >= 250) {
                jPressTime = System.currentTimeMillis();
                attackOne();
                jTimes++;
            } else if (state == State.RUN) {
                attackRun();
            } else if (state == State.JUMP) {
                attackJump();
            }

        } else if (jTimes == 2 && System.currentTimeMillis() - jPressTime >= 250) {
            jStopTime = 0;
            jPressTime = System.currentTimeMillis();
            attackTwo();
            jTimes++;
        } else if (jTimes == 3 && System.currentTimeMillis() - jPressTime >= 750) {
            jTimes = 1;
            jStopTime = 0;
            jPressTime = System.currentTimeMillis();
            attackThree();
        }

    }

    public long iStopTime = 0;   //收技能时间 判断x ms内，没有再次按下平i就收拳
    public boolean iOneReady = true; //判断是否第一段i键准备,否则是第二段i
    public long iPressTime = 0;  //i键按下时间

    public void keyI() {
        keyCode = KeyEvent.VK_I;
        if (state == State.STAND || state == State.WALK || state == State.RUN || state == State.SKILL_TWO_ONE || state == State.SKILL_TWO_TWO) {
            //第一次按i键
            if (iPressTime == 0) {
                new Thread(this).start();
                killTwoOne();
                iOneReady = false;
                bulletLike();
            }
            //第一段i技能
            if (iOneReady && System.currentTimeMillis() - iPressTime > 500 && iPressTime != 0) {
                killTwoOne();
                iOneReady = false;
                bulletLike();
            }
            //第二段i技能
            if (!iOneReady && System.currentTimeMillis() - iPressTime > 500 && iPressTime != 0) {
                killTwoTwo();
                iOneReady = true;
                bulletLike();
            }
        }

    }

    //技能二 气功波相同之处
    public void bulletLike() {
        iStopTime = 0;
        iPressTime = System.currentTimeMillis();
        //子弹池种获取
        Bullet bullet = BulletsPool.get();

        //生成子弹对象并添加子弹到子弹列表
        if (direction == Direction.RIGHT) {
            bullet.img = Toolkit.getDefaultToolkit().getImage("src/main/resources/img/davis_ball.png");
            bullet.dx1 = dx1 + 70;
            bullet.dy1 = dy1 + 18;
            bullet.dx2 = dx1 + 150;
            bullet.dy2 = dy1 + 45 + 18;
            bullet.sx1 = 0;
            bullet.sy1 = 0;
            bullet.sx2 = 80;
            bullet.sy2 = 45;
            bullet.direction = direction;
            bullet.gameFrame = gameFrame;
            gameFrame.bulletList.add(bullet);
        } else {
            bullet.img = Toolkit.getDefaultToolkit().getImage("src/main/resources/img/davis_ball_mirror.png");
            bullet.dx1 = dx1 - 50;
            bullet.dy1 = dy1 + 18;
            bullet.dx2 = dx1 + 30;
            bullet.dy2 = dy1 + 45 + 18;
            bullet.sx1 = 240;
            bullet.sy1 = 0;
            bullet.sx2 = 320;
            bullet.sy2 = 45;
            bullet.direction = direction;
            bullet.gameFrame = gameFrame;
//            Bullet bullet = new Bullet("src/main/resources/img/davis_ball_mirror.png", dx1 - 50, dy1 + 18, dx1 + 30, dy1 + 45 + 18, 240, 0, 320, 45, direction, gameFrame);
            gameFrame.bulletList.add(bullet);
        }
    }

    public boolean aRunReady = false;   //a键跑步状态是否就绪
    public long aReleaseTime = 0;  //a键松开时间

    public boolean dRunReady = false;   //d键跑步状态是否就绪
    public long dReleaseTime = 0;  //d键松开时间

    public void keyPA() {
        left = true;

        if (aRunReady) {
            if (System.currentTimeMillis() - aReleaseTime <= 200) {
                state = State.RUN;
                aRunReady = false;
                System.out.println("跑步");
            }
        }
    }

    public void keyPD() {
        right = true;

        if (dRunReady) {
            if (System.currentTimeMillis() - dReleaseTime <= 200) {
                state = State.RUN;
                System.out.println("跑步");
            }
        }
    }

    public void keyRA() {
        //松开的时候获取线程，200ms内再次按下激活跑步准备
        left = false;
        aReleaseTime = System.currentTimeMillis();
        aRunReady = true;   //跑步状态
        System.out.println(111111111);
        if (state == State.WALK || state == State.RUN) moveStop();//防止奔跑跳跃时，松开按键触发暂停
    }

    public void keyRD() {
        //松开的时候获取线程，200ms内再次按下激活跑步准备
        right = false;
        System.out.println(111111111);
        dReleaseTime = System.currentTimeMillis();
        dRunReady = true;   //跑步状态
        if (state == State.WALK || state == State.RUN) moveStop(); //防止奔跑跳跃时，松开按键触发暂停
    }

    public long mStopTime = 0;   //受伤结束时间 判断x ms内，

    @Override
    public void run() {
        while (true) {
            //j按键线程
            if (keyCode == KeyEvent.VK_J) {
                jStopTime += 100;
                if (jStopTime >= 1000) {
                    jStopTime = 0;
                    jTimes = 1;
                    moveStop();
                    return;
                }

            }

            if (keyCode == KeyEvent.VK_I) {
                iStopTime += 100;
                if (iStopTime >= 750) {
                    iPressTime = 0;
                    iStopTime = 0;
                    iOneReady = true;
                    moveStop();
                    return;
                }
            }

            if (keyCode == KeyEvent.VK_M) { //受伤的等待时间
                mStopTime += 100;
                if (mStopTime >= 1500) {   //这里设置1500是因为第二下出拳太慢了
                    mStopTime = 0;
                    moveStop();
                    return;
                }
            }

            try {
                Thread.sleep(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }


    }

    public void jump() {
        if (state != State.JUMP) { //跳跃时不准在跳跃
            //设置跳跃状态
            state = State.JUMP;

            sy1 = 480;
            sy2 = 560;

            if (direction == Direction.RIGHT) {
                changeTimerParameter = "右跳跃";
                sx1 = 160;
                sx2 = 240;
            } else {
                changeTimerParameter = "左跳跃";
                sx1 = 560;
                sx2 = 640;
            }
            changeOnStart();
            imgOnStart();
        }


    }

//    public void defense() {
//        imgOnEnd();
//        changeOnEnd();
//    }

    //这个移动停止后的动作，目前代表了所有操作后的停止动作
    public void moveStop() {
//        if (state == State.STAND || state == State.WALK || state == State.ATTACK_ONE || state == State.ATTACK_TWO || state == State.ATTACK_THREE || state == State.RUN) {
        if (state != State.ATTACK_RUN) {
            state = State.STAND;
            sy1 = 0;
            sy2 = 80;
            if (direction == Direction.RIGHT) {
                setImg(leftImg_0);
                sx1 = 240;
                sx2 = 320;
            } else {
                setImg(rightImg_0);
                sx1 = 480;
                sx2 = 560;
            }
            imgOnEnd();
        }
    }

    //内部类，来表示玩家血条 一是不会被包外的访问到，二是封装后期维护好，解耦
    class BloodBar {
        public static final int BAR_LENGTH = 80;
        public static final int BAR_HEIGHT = 8;

        public void draw(Graphics g) {
            //填充底色 黄色
            g.setColor(Color.GRAY);
            g.fillRect(dx1, dy2 + 10, BAR_LENGTH, BAR_HEIGHT);
            //当前血量 红色
            g.setColor(Color.RED);
            g.fillRect(dx1, dy2 + 10, hp, BAR_HEIGHT);   //hp 是当前生命值
            //边框  蓝色
            g.setColor(Color.BLUE);
            g.drawRect(dx1, dy2 + 10, BAR_LENGTH, BAR_HEIGHT);  //drawRect和上面的fillRect填充不一样

        }
    }


}
